package 动态规划;

public class No518零钱兑换II {

    /**
     * 给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。 
     *
     * 示例 1:
     * 输入: amount = 5, coins = [1, 2, 5]
     * 输出: 4
     * 解释: 有四种方式可以凑成总金额:
     * 5=5
     * 5=2+2+1
     * 5=2+1+1+1
     * 5=1+1+1+1+1
     * 示例 2:
     * 输入: amount = 3, coins = [2]
     * 输出: 0
     * 解释: 只用面额2的硬币不能凑成总金额3。
     * 示例 3:
     * 输入: amount = 10, coins = [10]
     * 输出: 1
     */


    /**
     * 重点巧妙解法:
     * (1)求排列:[1,2][2,1]两种情况
     *  两个for,钱在外,币额在内
     * (2)求组合:[1,2]没有[2,1]因为2和1已经组合了
     *  两个for,币额在外,钱在内
     */
    public int change(int amount, int[] coins) {

        if(amount==0||coins.length==0){
            return 1;
        }

        int[] dp=new int[amount+1];
        dp[0]=1;

        //组合数:币值在外    可不同顺序组合:币值在内
        for (int coin : coins) {
            for (int i = 1; i <= amount; i++) {
                if(i<coin){
                    continue;
                }
                dp[i]+=dp[i-coin];
            }
        }

        return dp[amount];
    }

    public static void main(String[] args) {
        No518零钱兑换II n=new No518零钱兑换II();
        int[] arr={1,2,5};
        int result = n.change(5, arr);
        System.out.println(result);
    }

}
